package edu.ncsu.csc.ip.client;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import edu.ncsu.csc.ip.client.protocol.ProtocolClientImpl;
import edu.ncsu.csc.ip.common.Log;

/**
 * Class <code></code>
 * 
 * 
 * 
 * @author Moin Ayazifar <mayazif@ncsu.edu>
 * @author Steven Elliott <sdelliot@ncsu.edu>
 * 
 */

public class ClientThread extends Thread {
	private DatagramSocket socket = null;
	private InetAddress address = null;
	private int port = 0;
	private ProtocolClientImpl protocol = new ProtocolClientImpl();
	private final int HEADER_SIZE = 8;
	private int timeout = 0;
	private byte[] buf;
	private long sequenceNumber;

	public ClientThread(InetAddress address, int port, byte[] buf,
			long sequenceNumber, int timeout) {
		super("ServerThread");
		this.port = port;
		this.buf = buf;
		this.sequenceNumber = sequenceNumber;
		this.timeout = timeout;
		try {
			this.address = address;
			this.socket = new DatagramSocket();
		} catch (SocketException e) {
			e.printStackTrace();
		}
	}

	public void run() {

		try {
			socket.setSoTimeout(timeout);
		} catch (SocketException e1) {
			e1.printStackTrace();
		}
		int seqNum = -1;
		byte[] ackPacket = new byte[HEADER_SIZE];
		DatagramPacket receivePacket = new DatagramPacket(ackPacket,
				ackPacket.length);
		DatagramPacket packet = new DatagramPacket(buf, buf.length, address,
				port);

		while (true) {
			try {
				socket.send(packet);
				socket.receive(receivePacket);
				try {
					seqNum = Integer.parseInt(protocol
							.parseMessage(receivePacket.getData()));
				} catch (NumberFormatException e) {
					e.printStackTrace();
				}

				if (seqNum >= sequenceNumber) {
					break;
				} else {
					System.out.println("Mismatch sequence numbers " + seqNum
							+ " and " + sequenceNumber
							+ ", retransmitting packet.");
					socket.send(packet);
					continue;
				}
			} catch (SocketTimeoutException ste) {
				Log.println("Timeout, sequence number = " + sequenceNumber);
				
				try {
					socket = new DatagramSocket();
					socket.setSoTimeout(timeout);
				} catch (SocketException e1) {
					e1.printStackTrace();
				}
				continue;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		socket.close();
	}
}
